/*
 * Copyright (c) 2021 Shenzhen Kaihong Digital Industry Development Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import app from '@system.app'

// @ts-ignore
import audio from '@ohos.multimedia.audio'

import fileio from '@ohos.fileio'

import featureAbility from '@ohos.ability.featureAbility'

// @ts-ignore
import CryptoJS from 'crypto-js'
//import Base64 from "js-base64";
import { Base64 } from 'js-base64';
// @ts-ignore
import WebSocket from '@ohos.websocket_napi';

const APPID = '5ff3fa4a'
const API_SECRET = 'de39f9c281086330d5552ebef8589a2a'
const API_KEY = '2497fb2675991234386031e0748ec3cd'
var ws = null;
var globalThis;
var audioData = []
var handlerInterval = null;
var dataArr=[]

export default {
    data: {
        text: "",
        bufSize: 1280,
        capturer: null,
        arrayBufGlobal: null,
        fd: 0,
        buttonText:"按住说话",
        resultTextTemp:"",
        imgPath: "common/images/engine.png",
        isWebConnect: false,
        displayStr: "",
    },
    onInit() {
        this.capturer = audio.createAudioCapturer(audio.AudioVolumeType.MEDIA);
        globalThis = this;

        //WebSocket连接
//        console.log("gyf onInit");
//        this.connectWebSocket();
    },

    record() {
        this.buttonText = "松开停止"
        //this.connectHttp();
        //this.connectWebSocket()
        //        console.log("gyf record 11111");
        this.initRecord()
    },

    initRecord(){
        globalThis.arrayBufGlocal = [];

        let pp = {
            'format':audio.AudioSampleFormat.SAMPLE_S16LE,
            'samplingRate':audio.AudioSamplingRate.SAMPLE_RATE_8000,
            'channels':audio.AudioChannel.MONO,
            'encoding':audio.AudioEncodingType.ENCODING_PCM,
            'deviceType':audio.DeviceType.MIC
        };

        var context = featureAbility.getContext();
        context.getOrCreateLocalDir().then(function (dir) {
            let path = dir + "/audio_record.pcm";
            console.log("gyf path = " + path);
            //打开录音文件
            globalThis.fd = fileio.openSync(path, 0o2|0o100|0o1000, 0o666);

        });

        console.log("gyf record 22222 globalThis.fd = " + globalThis.fd);

        globalThis.capturer.setParams(pp).then(function () {
            console.log("gyf setParams finish");

            globalThis.capturer.start().then(function (result) {
                console.log("gyf start1 result = " + result);
                globalThis.getBuf(1280);
            });
        })
    },

    //循环调用read，进行数据的读取
    handleBuffer(arrayBuffer) {
        console.log("gyf handleBuffer");

        fileio.writeSync(globalThis.fd, arrayBuffer);
        let that = this;
//        ws.send(arrayBuffer, (err)=>{
//            if(err){
//                that.text +="\n"+"发送成功"
//            }else{
//                that.text +="\n"+"发送失败"
//            }
//        });

        //        this.arrayBufGlobal = this.arrayBufGlobal + arrayBuffer;
        //        console.log("gyf arrayBuffer len = [" + arrayBuffer.byteLength + "]");
        //        console.log("gyf global arrayBuffer len = [" + this.arrayBufGlobal.byteLength + "]");
        globalThis.capturer.read(globalThis.bufSize, true).then(this.handleBuffer);

    },

    appExit() {
        app.terminate()
    },

    getData(bufSize) {
        console.log("gyf getData");
        globalThis.capturer.read(bufSize, true).then(this.handleBuffer);
        console.log("gyf getData read 222");
    },

    getBuf(bufSize) {
        console.log("gyf getBuf");
        this.getData(bufSize);
    },

    recordstop() {
        console.log("gyf recordstop");
        this.buttonText = "按住说话"
        globalThis.capturer.stop().then(function (result) {
            console.log("gyf stop result = " + result);
        });
//        ws.close((err)=>{
//            console.log('wsclose--' + err);
//        });
    },

    //连接websocket
    connectWebSocket() {
        console.log("gyf connectWebSocket()");
        return this.getWebSocketUrl().then(url => {
            console.log('getWebSocketUrl--' + url)
            //let iatWS
            if(ws != null){
                ws = null
            }
            this.text +="\n"+"websocket正在连接1"
            ws = WebSocket.createWebSocket();
            this.text +="\n"+"websocket正在连接"
            let that = this;
            ws.on('message', (value) => {
                let jsonData = JSON.parse(value)
                this.result(jsonData.data)
            });
            ws.on("error",(str)=>{
                console.info("jhx 应用 1 订阅 error 回调结果 " + str);
                that.text +="\n"+"websocket连接失败1" + str
                that.isWebConnect = false;
            });
            ws.on("close",(code, reason)=>{
                console.info("jhx 应用 1 订阅code 回调结果 code " + code + " reason " + reason);
                that.text +="\n"+"websocket连接失败2 code " + code + " reason " + reason;
                that.isWebConnect = false;
            });
            ws.connect(url, (err) => {
                console.log('gyf connect--' + err)
                if (err) {
                    that.text +="\n"+"websocket连接成功";
                    console.log("gyf ws connect success");
                    that.isWebConnect = true;
                } else {
                    that.text +="\n"+"websocket连接失败";
                    console.log("gyf ws connect fail");
                    that.isWebConnect = false;
                }
            });
        })
    },

    getWebSocketUrl() {
        return new Promise((resolve, reject) => {
            // 请求地址根据语种不同变化
            var url = 'ws://iat-api.xfyun.cn/v2/iat'
            var host = 'iat-api.xfyun.cn'
            var apiKey = API_KEY
            var apiSecret = API_SECRET
            // @ts-ignore
            var date = new Date().toGMTString()
            console.log('gyf date--' + date)
            var dateString = date.replace(/,/g,"%2C").replace(/ /g,"%20").replace(/:/g,"%3A")
            var algorithm = 'hmac-sha256'
            var headers = 'host date request-line'
            var signatureOrigin = `host: ${host}\ndate: ${date}\nGET /v2/iat HTTP/1.1`
            console.log('gyf signatureOrigin--' + signatureOrigin)
            var signatureSha = CryptoJS.HmacSHA256(signatureOrigin, apiSecret)
            console.log('gyf signatureSha--' + signatureSha)
            var signature = CryptoJS.enc.Base64.stringify(signatureSha)
            var authorizationOrigin = `api_key="${apiKey}", algorithm="${algorithm}", headers="${headers}", signature="${signature}"`
            var test = `signature="${signature}"`
            var test1 = Base64.encode(test)
            var authorization = Base64.encode(authorizationOrigin)
            url = `${url}?authorization=${authorization}&date=${dateString}&host=${host}`
            resolve(url)
        })
    },

    toBase64(buffer) {
        var binary = ''
        var bytes = new Uint8Array(buffer)
        console.log("bytes--"+bytes)
        var len = bytes.length
        for (var i = 0; i < len; i++) {
            binary += String.fromCharCode(bytes[i])
        }
        return Base64.btoa(binary)
    },

    reqXunfei(path){
        this.text = "正在模拟语音识别中。。。"
        var context = featureAbility.getContext();
        let that = this;
//        let path =  "/data/audio_record.pcm";
        let fd = fileio.openSync(path, 0o2);
        let buf = new ArrayBuffer(200000);
//        this.text = "\nbyteLength1" + buf.byteLength
        //实际读取长度
        let num = fileio.readSync(fd, buf);
        var realBuf = new Int8Array(buf.slice(0,num))
//        this.text = "\n" + num +  "\nbyteLength2" + realBuf.length
        for(var i =0;i<realBuf.length;i++){
            audioData.push(realBuf[i])
        }
        this.connectWebSocketTest()
    },

    connectWebSocketTest() {
        console.log("gyf connectWebSocketTest");
        return this.getWebSocketUrl().then(url => {
            console.log('gyf getWebSocketUrl--' + url)
            if(ws != null){
                ws = null
            }
            console.log("gyf connectWebSocketTest111");
//            this.text ="\n"+"websocket正在连接1"
            ws = WebSocket.createWebSocket();
//            this.text ="\n"+"websocket正在连接2"
            console.log("gyf connectWebSocketTest222");
            let that = this;
            ws.on('message', (value) => {
                console.log("gyf ws.on message");
                let jsonData = JSON.parse(value)
                that.isWebConnect = true;
                this.result(jsonData)
            });
            ws.on("error",(str)=>{
                console.info("gyf 应用 1 订阅 error 回调结果 " + str);
               // that.text +="\n"+"websocket连接失败1" + str
                that.text = "订阅 error 回调结果 " + str;
                that.isWebConnect = false;
            });
            ws.on("close",(code, reason)=>{
                clearInterval(handlerInterval)
                console.info("gyf 应用 1 订阅code 回调结果 code " + code + " reason " + reason);
                that.text ="code " + code + " reason " + reason;
                that.isWebConnect = false;
            });
            console.log("gyf connectWebSocketTest333");
            ws.connect(url, (err) => {
                console.log('gyf connect--' + err)
                if (err) {
                    that.text ="websocket连接成功"
                    that.isWebConnect = true;
                    setTimeout(() => {
                        that.webSocketSend();
                    }, 500)
                } else {
                    that.text = "websocket连接失败"
                    that.isWebConnect = false;
                }
            });
        })
    },

    webSocketSend() {
//        this.text = ""
        let audioDataSend = audioData.splice(0, 1280)
        var params = {
            common: {
                app_id: APPID,
            },
            business: {
                language: 'zh_cn', //小语种可在控制台--语音听写（流式）--方言/语种处添加试用
                domain: 'iat',
                accent:'mandarin', //中文方言可在控制台--语音听写（流式）--方言/语种处添加试用
                vad_eos: 5000,
                dwa: 'wpgs', //为使该功能生效，需到控制台开通动态修正功能（该功能免费）
            },
            data: {
                status: 0,
                format: 'audio/L16;rate=8000',
                encoding: 'raw',
                //audio:dataArr[count]}
                audio:this.toBase64(audioDataSend)},
        }

        console.log("gyf webSocketSend1--" + JSON.stringify(params))
        let that = this
//        console.log("gyf webSocketSend status 0");
        ws.send(JSON.stringify(params), (err)=>{});
        handlerInterval = setInterval(() => {
            // websocket未连接
            //that.text ="\naudioData.length"+audioData.length
            if (audioData.length === 0) {
            //if(count == dataArr.length){
                let endParams = {
                    data: {
                        status: 2,
                        format: 'audio/L16;rate=8000',
                        encoding: 'raw',
                        audio: "",
                    },
                }
                console.log("gyf webSocketSend2--" + JSON.stringify(endParams))
                ws.send(JSON.stringify(endParams), (err)=>{});
                audioData = []
                clearInterval(handlerInterval)
                return false
            }
            //that.text ="\naudioDataSend1--"+audioDataSend.length+"audioData.length1--"+audioData.length
            audioDataSend = audioData.splice(0, 1280)
            //that.text ="\naudioDataSend2--"+audioDataSend.length+"audioData.length2--"+audioData.length
//            // 中间帧
            let midParams = {
                data: {
                    status: 1,
                    format: 'audio/L16;rate=8000',
                    encoding: 'raw',
                    //audio:dataArr[count]
                    audio: that.toBase64(audioDataSend),
                },
            }
            ws.send(JSON.stringify(midParams), (err)=>{});
        }, 500)
    },

    result(jsonData) {
        // 识别结束
        console.log("gyf 测试中文显示");
        console.log("gyf result---"+JSON.stringify(jsonData))
        if (jsonData.data && jsonData.data.result) {
            console.log("gyf jsonData.data---"+JSON.stringify(jsonData.data))
            let data = jsonData.data.result
            console.log("gyf jsonData.data.result---"+JSON.stringify(data))
            let str = ''
            let resultStr = ''
            let ws = data.ws
            for (let i = 0; i < ws.length; i++) {
                str = str + ws[i].cw[0].w
            }
            // 开启wpgs会有此字段(前提：在控制台开通动态修正功能)
            // 取值为 "apd"时表示该片结果是追加到前面的最终结果；取值为"rpl" 时表示替换前面的部分结果，替换范围为rg字段
            if (data.pgs) {
                if (data.pgs === 'apd') {
                    // 将resultTextTemp同步给resultText
                    this.text = this.text + str + "  语音识别结束"
                } else {
                    this.text = str + "  语音识别结束"
                }
            } else {
                this.text = this.text + str + "  语音识别结束"
            }

            this.displayStr += str;

            console.log("gyf resultText3 str--" + str)

        }
        console.log("lsm jsonData.code---"+jsonData.code)
        console.log("lsm jsonData.data.status---"+jsonData.data.status)
        if (jsonData.code === 0 && jsonData.data.status === 2) {
            ws.close((err)=>{
                console.log('gyf wsclose-- 111' + err);
            });
            this.displayPic(this.displayStr);
        }
        if (jsonData.code !== 0) {
            ws.close((err)=>{
                console.log('gyf wsclose-- 222' + err);
            });
            console.log(`${jsonData.code}:${jsonData.message}`)
        }
    },

    interiorTest() {
        this.displayStr = "";
        this.reqXunfei("/data/audio/interior.pcm");
    },

    appearanceTest() {
        this.displayStr = "";
        this.reqXunfei("/data/audio/appearance.pcm");
    },

    engineTest() {
        this.displayStr = "";
        this.reqXunfei("/data/audio/engine.pcm");
    },

    tailTest() {
        this.displayStr = "";
        this.reqXunfei("/data/audio/tail.pcm");
    },

    displayPic(str) {
        console.log("gyf displayPic str = " + str);
        if (null == str || "" == str) {
            console.log("gyf displayPic str is null");
            return;
        }

        console.log("gyf displayPic str222");

        if (str.indexOf("内饰") != -1 || str.indexOf("内室") != -1) {
            this.imgPath = "common/images/interior.png";
            this.text = "展示内饰";
            console.log("gyf 内饰");
        } else if (str.indexOf("外观") != -1) {
            this.imgPath = "common/images/appearance.png";
            this.text = "展示外观";
            console.log("gyf 外观");
        } else if (str.indexOf("引擎") != -1) {
            this.imgPath = "common/images/engine.png";
            this.text = "展示引擎";
            console.log("gyf 引擎");
        } else if (str.indexOf("尾部") != -1) {
            this.imgPath = "common/images/tail.png";
            this.text = "展示尾部";
            console.log("gyf 尾部");
        }

        console.log("gyf displayPic end");
    },
}

